/*
    内存管理系统
 */
public class MemorySystem {
    //内存抽象
    private DataBlock[] mainMemory;
    //帧表
    private FrameTable frameTable;
    //内存大小
    private int memorySize;
    //是否初始化
    private boolean hasInit;
    private static final MemorySystem memorySystem = new MemorySystem();
    private MMU mmu;
    //调页时无空闲页所用的LRU数据结构
    private LRUList lruList;

    private MemorySystem() {

    }

    public DataBlock malloc(int processID) {
        for (int frameNum = 0; frameNum < memorySize; frameNum++) {
            if(!frameTable.getBitMap()[frameNum]){
                frameTable.addNewLinkToFrameTable(processID,0,frameNum);
                LRUListUnit tempUnit = new LRUListUnit(frameTable.getFrameTable()[frameNum]);
                lruList.add(tempUnit);
                return mainMemory[frameNum];
            }
        }
        return null;
    }

    //pageNum表示是当前进程的第几页
    public DataBlock malloc(Process process, int pageNum) {
        for (int frameNum = 0; frameNum < memorySize; frameNum++) {
            //第i页是空闲的
            if (!frameTable.getBitMap()[frameNum]) {
                process.getPCB().setValidBit(pageNum, true);
                LRUListUnit tempUnit = new LRUListUnit(frameTable.getFrameTable()[frameNum]);
                lruList.add(tempUnit);
                return mainMemory[frameNum];
            }
        }

        return null;
    }

    public DataBlock link(Process process,int pageNum,int frameNum){
        process.getPCB().setValidBit(pageNum,true);
        frameTable.addNewLinkToFrameTable(process.getPCB().getProcessID(),pageNum,frameNum);
        LRUListUnit tempUnit = new LRUListUnit(frameTable.getFrameTable()[frameNum]);
        lruList.flash(tempUnit);
        return mainMemory[frameNum];
    }

    public void free(Process process, int pageNum) {
        process.getPCB().setValidBit(pageNum, false);
        int frameNum = process.getPCB().getPageTable().get(pageNum).getFrameNumber();
        frameTable.removeLinkToFrameTable(process, pageNum, frameNum);
        LRUListUnit tempUnit = new LRUListUnit
                (frameTable.getFrameTable()[process.getPCB().getPageTable().get(pageNum).getFrameNumber()]);
        lruList.deleteUnit(tempUnit);
    }

    public boolean initMainMemory(int mainMemorySize) {
        if (hasInit) {
            return false;
        }
        memorySize = mainMemorySize;
        hasInit = true;
        frameTable = new FrameTable(mainMemorySize);
        mainMemory = new DataBlock[mainMemorySize];
        for (int i = 0; i < mainMemorySize; i++) {
            mainMemory[i] = new DataBlock();
        }
        return true;
    }

    public static MemorySystem getMemorySystem() {
        return memorySystem;
    }


}
